Ansible最重要的就是playbook.yml啦
當我們用Vagrant建好vm後,再來每個vm要安裝的、要設定的就靠Ansible了
本篇參考:https://www.vagrantup.com/docs/provisioning/ansible_intro.html
Vagrantfile就會運行Ansible啦
Vagrant.configure("2") do |config|
# ansible,在Vagrant host上執行Ansible
# ansible_local,在Vagrant guest上執行Ansible
config.vm.provision :ansible do |ansible|
ansible.playbook = "playbook.yml"
end
end
ansible.cfg # 告訴 ansible 什麼檔案放哪裡
[defaults]
inventory = hosts # inventory
remote_user = vagrant
private_key_file = ~/.ssh/id_rsa
host_key_checking = false # 不問是否加入 ssh 的 key
hosts # inventory檔,用來定義ansible的Managed node們
[dev] # 情境
ansible_ssh_host: masterNode1
ansible_ssh_port: 22
ansible_ssh_user: vagrant
ansible_ssh_private_key_file = ~/ssh/id_rsa
playbook.yml
有關playbook重要知識,請參考官網文件
https://docs.ansible.com/ansible/latest/user_guide/playbooks_special_topics.html
例如果要保護機敏資訊(連線字串、password…)就看 Using Vault in playbooks
在playbook看到不懂的關鍵字
先到官網的playbook keywords找看看
https://docs.ansible.com/ansible/latest/reference_appendices/playbooks_keywords.html
---
- name: play1 # 一整組都算
hosts: all
tasks:
- name: ensure ntpd is at the latest version # task 1
yum: pkg=ntp state=latest # module (command、apt、lineinfile)
notify:
- restart ntpd
- name: task 2
command: echo "Hello World"
handlers:
- name: restart ntpd
service: name=ntpd state=restarted
# ================play1 end======================
- name: play2 #
hosts: all
tasks:
- name: ensure ntpd is at the latest version
yum: pkg=ntp state=latest
notify:
- restart ntpd
handlers:
- name: restart ntpd
service: name=ntpd state=restarted
$ ansible-playbook playbook.yml
$ vagrant provision # 要在Vagrantfile 裡面定義 ansible.playbook = "playbook.yml"
用vagrant跑ansible,應該會自動建立inventory
.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory
inventory應該是「vm清單」,但其實還可以給一堆參數
# Generated by Vagrant
machine ansible_ssh_host=127.0.0.1 ansible_ssh_port=2222
手動執行ansible,
-i inventory
-- private-key 指定private key
-u ssh的username
playbook.yml 要作的腳本
$ ansible-playbook -i .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory --private-key=.vagrant/machines/default/virtualbox/private_key -u vagrant playbook.yml
--verbose modules執行成功的訊息也顯示
--list-hosts 會影響到哪些 hosts
寫得有點亂,接下來…
一起學習官網的範例吧
Ansible的版本變更很快,新舊文件的yml檔的寫也法也差異很大
我在寫此文章的時候是2.6(2018年10月),如果您在看此文章時已是n年後,此篇就沒啥參考價值啦
https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html#basics
簡體中文的(版本舊很多)
https://ansible-tran.readthedocs.io/en/latest/docs/playbooks_roles.html
module可以到這裡查,每個module都還有範例,不怕寫不出來
https://docs.ansible.com/ansible/latest/modules/list_of_all_modules.html
# 最上層沒有name,只有1個play。
---
- hosts: webservers
vars: # 有2個vars
http_port: 80
max_clients: 200
remote_user: root # user account
tasks: # 有3個taskS
- name: install the latest version of Apache(如果已是最新就不會再裝)
yum: # module,應該是受控端有yum package manager的才能用吧
name: httpd
state: latest
- name: write the apache config file
template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
notify: # 在 task 結束時 triggered(觸發) ,叫 handler 做事情,我也不知怎麼翻譯
- restart apache
- name: ensure apache is running # 確定 httpd 是 started
service:
name: httpd
state: started
handlers: # 有點像可重複使用的tasks(數個tasks會call的,就抽到handlers)
- name: restart apache
service:
name: httpd
state: restarted
# 也可以用 listen 一次觸發多個 handler
handlers:
- name: restart memcached # 如果 handler 的 name 一樣,只會跑1個
service:
name: memcached
state: restarted
listen: "restart web services" # 1
- name: restart apache
service:
name: apache
state:restarted
listen: "restart web services" # 2
tasks:
- name: restart everything
command: echo "this task will restart the web services"
notify: "restart web services" # 跑上面1、2(依順序)
---
- hosts: webservers
remote_user: yourname
tasks:
- service:
name: nginx
state: started
become: yes # 啟用升權限 privilege escalation
become_method: sudo # 如果需要打密碼, ansible-playbook --ask-become-pass (-K)
# become_user: mongodbAccount # 變成非root的user
# (例如:你要操作mongodb時,轉成mongodbAccount的帳號)
become_method: su
# 用 su (sudo/su/pbrun/pfexec/doas/dzdo/ksu/runas/machinectl) 預設是sudo
# become_method 在play或task可使用 蓋掉ansible.cfg設定的值
- name: Run a command as nobody
command: somecommand
become: yes
become_method: su
become_user: nobody
# 在task或role可使用
become_flags: '-s /bin/sh' # 當shell是nologin的時候,使用nobody帳號,跑somecommand
# webserver 這台主機,使用manager帳號登入,登入後要提權
webserver ansible_user=manager ansible_become=yes
# ansible_become_method (類似become_method), ansible_become_pass設定提權密碼
- hosts: all
order: sorted
# 執行順序(inventory,reverse_inventory,sorted,reverse_sorted,shufflt)
# 預設是依 inventory 順序執行
gather_facts: False # 不收集遠端host的變數
tasks:
- debug:
var: inventory_hostname
# action 使用 command 或 shell
- name: enable selinux
command: /sbin/setenforce 1
# 下的指令 return ture,或者乎略錯誤 ignore_errors: True
- name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true
- name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: True
# 使用變數,定義在vars section
- name: create a virtual host file for {{ vhost }}
template:
src: somefile.j2 # j2樣板語言
dest: /etc/httpd/conf.d/{{ vhost }}
---
# possibly saved as tasks/foo.yml
- name: echo wp_user
shell: echo {{ wp_user }}
- name: placeholder bar
command: /bin/bar
tasks:
- include_tasks: tasks/foo.yml
- include_tasks: wordpress.yml wp_user=timmy # 可以給參數
# 新的語法
- { include_tasks: wordpress.yml, wp_user: timmy, ssh_keys: [ 'keys/one.txt', 'keys/two.txt' ] }
# 其他給變數的方式
- include_tasks: wordpress.yml
vars:
wp_user: timmy
some_list_variable:
- alpha
- beta
- gamma
# 也可以在 handlers section 使用 include
handlers:
- include_tasks: handlers/handlers.yml # import 跟 include 的 差異 我也不知道~~
- import_tasks: handlers/handlers.yml
# 也可以用一個yml來import多個playbook
- import_playbook: webservers.yml
- import_playbook: databases.yml
我們不學怎麼封裝Role,只試圖來瞭解Role,進而使用Role
# 目錄結構,範例
site.yml
webservers.yml
fooservers.yml
roles/
common/ # 名字叫「common」的role
tasks/ # 執行此 role 時的 main list of tasks
handlers/
files/
templates/
vars/ # 其他的變數
defaults/ # 預設變數
meta/ # meta data
webservers/ # 名字叫「webservers」的role
tasks/
defaults/
meta/
所以如果有個role叫x,可能會長這樣:
roles / x / tasks / main.yml
roles / x / handlers / main.yml
roles / x / vars / main.yml
roles / x / defaults / main.yml
roles / x / meta / main.yml
roles/x/{files,templates,tasks}/ (dir depends on task)
來參考檔案
1.pre_tasks
2.被觸發的handlers
3.roles裡的role # role的相依關係定義在meta/main.yml (不執行的條件之類的filter,condition)
4.tasks
5.post_tasks
# roles/example/tasks/main.yml # 名字叫「example」的role
- name: added in 2.4, previously you used 'include'
import_tasks: redhat.yml
when: ansible_os_platform|lower == 'redhat' # 很好懂吧 when 'redhat' 就 import redhat.yml
- import_tasks: debian.yml
when: ansible_os_platform|lower == 'debian'
# roles/example/tasks/redhat.yml
- yum:
name: "httpd"
state: present
# roles/example/tasks/debian.yml
- apt:
name: "apache2"
state: present
---
- hosts: webservers
roles:
- common
- webservers
在 playbook 中可以用 import_role、include_role
---
- hosts: webservers
tasks:
- debug:
msg: "before we run our role"
- import_role: # static
name: example
- include_role: # dynamic
name: example
- debug:
msg: "after we ran our role"
roles:
- role: '/path/to/my/roles/common'
---
- hosts: webservers
roles:
- role: bar
tags: ["foo"]
vars: # 給變數
message: "first"
# using YAML shorthand, 較新的語法
- { role: foo, tags: ["bar", "baz"], vars: { message: "second" } }
# 或者這樣寫也可以
---
- hosts: webservers
tasks:
- import_role:
name: foo
tags:
- bar
- baz
# roles/myapp/meta/main.yml 定義在meta裡
# Role Dependencies 在 該role之前執行
present
---
dependencies:
- role: common
vars:
some_parameter: 3
- role: apache
vars:
apache_port: 80
# meta/main.yml
---
dependencies:
- role: wheel # 執行順序3
vars:
n: 1
- role: wheel
vars:
n: 2
- role: wheel
vars:
n: 3
- role: wheel
vars:
n: 4
---
dependencies:
- role: tire # 執行順序1
- role: brake # 執行順序2
---
allow_duplicates: true # 設ture,同一個role wheel給不同的參數才會都執行
執行結果:
tire(n=1)
brake(n=1)
wheel(n=1)
tire(n=2)
brake(n=2)
wheel(n=2)
...
car
目錄結構會像下面,我們只要會用、看得懂即可
roles/
my_custom_modules/
library/
module1
module2
roles/
my_custom_filter/
filter_plugins
filter1
filter2
roles/
/etc/ansible/roles
tasks:
- name: Attempt and graceful roll back demo
block: # 正常跑這個section
- debug:
msg: 'I execute normally'
- command: /bin/false
- debug:
msg: 'I never execute, due to the above task failing'
rescue: # 當block有error時執行
- debug:
msg: 'I caught an error'
- command: /bin/false
- debug:
msg: 'I also never execute :-('
always: # 都會跑
- debug:
msg: "This always executes"
===
很不好意思,
今天只有介紹「內功心法」
其實module才是「武功招式」,
結果module只有寫whoami就來不及寫了~
就到(10/29了)
提供一些連結,role遇到什麼就認真查文件囉@@~
command: whoami
register: check_user # 註冊一個變數variable,把whoami的輸出,存到check_user變數
debug: msg="{{ check_user }}" # 顯示變數{{check_user}},方便除錯
===